﻿using System;
using System.Linq;

using octalforty.Componento.Core.Util;

namespace octalforty.Componento.Core.ObjectModel
{
    public class VersionRequirement
    {
        public Version Version
        { get; private set; }

        public VersionInterval Interval
        { get; private set; }

        public VersionRequirement(Version version)
        {
            Version = version;
        }

        public VersionRequirement(VersionInterval interval)
        {
            Interval = interval;
        }

        public static implicit operator VersionRequirement(Version version)
        {
            return new VersionRequirement(version);
        }

        public static VersionRequirement Parse(string s)
        {
            try
            {
                if(string.IsNullOrEmpty(s)) return new VersionRequirement(new Version(0, 0));
                if(!s.Contains(",")) return new VersionRequirement(new Version(s.Trim('[', ']', '(', ')')));

                var parts = s.Trim('[', ']', '(', ')').Split(new[] { ',' }, StringSplitOptions.None);
                var type = s[0].ToString() + s.Last();

                return new VersionRequirement(new VersionInterval(parts[0], parts[1], ToVersionIntervalType(type)));
            } // try
            catch(Exception e)
            {
                throw new FormatException("Could not parse '{0}' as a version requirement".FormatWith(s), e);
            } // catch
        }

        private static VersionIntervalType ToVersionIntervalType(string interval)
        {
            switch(interval)
            {
                case "[]":
                    return VersionIntervalType.Closed;
                case "[)":
                    return VersionIntervalType.ClosedOpen;
                case "(]":
                    return VersionIntervalType.OpenClosed;
                case "()":
                    return VersionIntervalType.Open;
                default:
                    throw new ArgumentOutOfRangeException("interval");
            }
        }

        public override string ToString()
        {
            if(Version != null)
                return Version.ToString();

            var format = string.Format(GetFormat(Interval.Type), "{0}, {1}");
            return format.FormatWith(Interval.Min, Interval.Max);
        }

        private string GetFormat(VersionIntervalType type)
        {
            switch(type)
            {
                case VersionIntervalType.Open:
                    return "({0})";
                case VersionIntervalType.Closed:
                    return "[{0}]";
                case VersionIntervalType.OpenClosed:
                    return "({0}]";
                case VersionIntervalType.ClosedOpen:
                    return "[{0})";
                default:
                    throw new ArgumentOutOfRangeException("type");
            }
        }
    }

    public class PlatformSpecification
    {
        
    }
}
